﻿using Net.EasyYf.Model;
using Net.EasyYf.Utils.Common;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Unity;

namespace Net.EasyYf.Services
{
    public class BaseEasyService
    {
        [Dependency]
        public EasyDbContext Db { get; set; }

        /// <summary>
        /// 获取表达式树
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public Expression<Func<T, bool>> GetExpression<T>()
        {
            return ExpressionHelper.True<T>();
        }


        /// <summary>
        /// 查询满足条件的实体个数  泛型方法
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public int Count<T>(Expression<Func<T, bool>> predicate = null) where T : class
        {

            if (predicate == null)
            {
                return Db.Set<T>().Count();
            }
            return Db.Set<T>().Count(predicate);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="T"> 实体类</typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalRecord"></param>
        /// <param name="whereLamdba"></param>
        /// <param name="orderName"></param>
        /// <param name="isAsc"></param>
        /// <returns></returns>
        public IEnumerable<T> FindPageList<T>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba = null, string orderName = "Id", bool isAsc = false) where T : class
        {

            var _list = Db.Set<T>().AsQueryable();
            if (whereLamdba != null)
            {
                _list = _list.Where(whereLamdba);
            }
            totalRecord = _list.Count();
            _list = OrderBy(_list, orderName, isAsc).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
            return _list.ToList<T>();

        }



        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <param name="isAsc"></param>
        /// <returns></returns>
        public IQueryable<T> OrderBy<T>(IQueryable<T> source, string propertyName, bool isAsc) where T : class
        {
            if (source == null) throw new ArgumentNullException("source", "不能为空");
            if (string.IsNullOrEmpty(propertyName)) return source;
            var _parameter = Expression.Parameter(source.ElementType);
            var _property = Expression.Property(_parameter, propertyName);
            if (_property == null) throw new ArgumentNullException("propertyName", "属性不存在");
            var _lambda = Expression.Lambda(_property, _parameter);
            var _methodName = isAsc ? "OrderBy" : "OrderByDescending";
            var _resultExpression = Expression.Call(typeof(Queryable), _methodName, new Type[] { source.ElementType, _property.Type }, source.Expression, Expression.Quote(_lambda));
            return source.Provider.CreateQuery<T>(_resultExpression);
        }



        public T Add<T>(T entity, bool isSave = true) where T : class
        {
            Db.Set<T>().Add(entity);
            if (isSave) Db.SaveChanges();
            return entity;
        }

        public int AddRange<T>(IEnumerable<T> entities, bool isSave = true) where T : class
        {

            Db.Set<T>().AddRange(entities);
            return isSave ? Db.SaveChanges() : 0;

        }

        public bool Update<T>(T entity, bool isSave = true) where T : class
        {

            Db.Set<T>().Attach(entity);
            Db.Entry<T>(entity).State = EntityState.Modified;
            return isSave ? Db.SaveChanges() > 0 : true;

        }

        public bool Delete<T>(T entity, bool isSave = true) where T : class
        {

            Db.Set<T>().Attach(entity);
            Db.Entry<T>(entity).State = EntityState.Deleted;
            return isSave ? Db.SaveChanges() > 0 : true;

        }

        /// <summary>
        /// 删除找到的第一个
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="whereLambda"></param>
        /// <param name="isSave"></param>
        public bool Delete<T>(Expression<Func<T, bool>> whereLambda, bool isSave = true) where T : class
        {

            T _entity = Db.Set<T>().FirstOrDefault<T>(whereLambda);
            if (_entity != null)
            {
                return Delete(_entity, isSave);
            }
            return false;
        }


        public int DeleteRange<T>(IEnumerable<T> entities, bool isSave = true) where T : class
        {
            //先得到实体才能删除
            foreach (var entitie in entities)
            {
                Db.Set<T>().Attach(entitie);
            }
            Db.Set<T>().RemoveRange(entities);
            return isSave ? Db.SaveChanges() : 0;

        }

        /// <summary>
        /// 是否存在满足条件的实体
        /// </summary>
        /// <param name="anyLambda"></param>
        /// <returns></returns>
        public bool Exist<T>(Expression<Func<T, bool>> anyLambda) where T : class
        {
            return Db.Set<T>().Any(anyLambda);
        }

        public T Find<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            T _entity = Db.Set<T>().FirstOrDefault<T>(whereLambda);
            return _entity;
        }

        public IEnumerable<T> FindAll<T>() where T : class
        {

            var data = Db.Set<T>();
            var _list = Db.Set<T>().AsEnumerable();
            return _list.ToList<T>();

        }


        public IEnumerable<T> FindList<T>(Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc) where T : class
        {

            var _list = Db.Set<T>().Where(whereLamdba);
            _list = OrderBy(_list, orderName, isAsc);
            return _list.ToList<T>();

        }


        public IEnumerable<T> FindListBySql<T>(string sql, params object[] parameters) where T : class
        {

            if (string.IsNullOrEmpty(sql)) return null;
            return Db.Database.SqlQuery<T>(sql, parameters);

        }

        public IEnumerable<F> FindPageListBySql<F>(int pageIndex, int pageSize, out int totalRecord, string orderName, bool isAsc, string sql, params object[] parameters) where F : class, new()
        {

            var _list = Db.Database.SqlQuery<F>(sql, parameters).AsQueryable();
            totalRecord = _list.Count();
            _list = OrderBy<F>(_list, orderName, isAsc).Skip<F>((pageIndex - 1) * pageSize).Take<F>(pageSize);
            return _list.ToList<F>();

        }
    }
}
